package edu.uoc.tdp.pac4.connexiomanteniment;

import java.util.*;
import edu.uoc.tdp.pac4.connexiomanteniment.exceptions.*;
import edu.uoc.tdp.pac4.connexiomanteniment.gui.PantallaGestioUsuaris;
import edu.uoc.tdp.pac4.server.connexiomanteniment.db.*;
import edu.uoc.tdp.pac4.server.connexiomanteniment.exceptions.*;
import edu.uoc.tdp.pac4.beans.Estudiante;

public class GestorAcces {
	
	public static final int MAXIM_INTENTS = 5;
	
	private static HashMap<String,Integer> elsIntents;   // Els diferents intents de login que es fan durant la sessio amb aquest client
														 // Guardarem els logins usats i el nombre d'intents amb cada login
	
	
	public GestorAcces() { if (elsIntents == null) elsIntents = new HashMap<String,Integer>(); }
	
	public Usuari validarUsuari(String login, String password) throws ExceptionLogin {
		
		if (login == null || login.trim().equals("")) throw new ExceptionLogin("PantallaError.ErrorLogin.missingLogin");
		if (password == null || password.trim().equals("")) throw new ExceptionLogin("PantallaError.ErrorLogin.missingPassword");	

		incrementaComptadorIntents(login);
		Integer intents = obtenirComptadorIntents(login);
		Usuari u = null;
		try { u = obtenirUsuari(login); }
		catch (ExceptionServer e) {
			String s = e.getErrorCode();
			if (s == null || "".equals(s)) throw new ExceptionLogin("PantallaError.ErrorLogin.");
			if (ExceptionServer.SERVER_DB_CONNECTION_FAILED.equals(s)) throw new ExceptionLogin("PantallaError.ErrorLogin.CannotConnectServer");
			if (ExceptionServer.SERVER_DB_INCORRECT_PROPERTY_FILE.equals(s)) throw new ExceptionLogin("PantallaError.ErrorLogin.ErrorReadingPropertyFile");
			if (ExceptionServer.SERVER_DB_PROPERTY_FILE_NOT_FOUND.equals(s)) throw new ExceptionLogin("PantallaError.ErrorLogin.PropertyFileNotFound");
			if (ExceptionServer.SERVER_DB_DRIVER_NOT_FOUND.equals(s)) throw new  ExceptionLogin("PantallaError.ErrorLogin.DBDriverNotFound");
			if (ExceptionServer.SERVER_DB_MISSING_VALUE.equals(s)) throw new ExceptionLogin("PantallaError.ErrorLogin.DBMissingValue");
			if (ExceptionServer.SERVER_DB_UNKNONW_TABLE.equals(s)) throw new ExceptionLogin("PantallaError.ErrorLogin.UnknownDBTable");
			if (ExceptionServer.SERVER_DB_UNKNOWN_COLUMN.equals(s)) throw new ExceptionLogin("PantallaError.ErrorLogin.UnknownDBColumn");			
			if (ExceptionServer.SERVER_DB_UNEXPECTED_ERROR.equals(s)) throw new ExceptionLogin("PantallaError.ErrorLogin.UnexpectedError");
		}
		if (u == null) {
			throw new ExceptionLogin("PantallaError.ErrorLogin.usuariNoTrobat");
		}
		if (u.getEstatEnSistema() == Usuari.ESTAT_EN_SISTEMA_BLOQUEJAT) {
			throw new ExceptionLogin("PantallaError.ErrorLogin.usuariBloquejat");
		}
		if (u.getEstatEnSistema() == Usuari.ESTAT_EN_SISTEMA_INACTIU) {
			throw new ExceptionLogin("PantallaError.ErrorLogin.usuariEsborrat");
		}
		if (!password.trim().equals(u.getPwd().trim())) {
			if (intents >= MAXIM_INTENTS) {
				// bloquejem l'usuari i llencem una excepcio
				u.setEstatEnSistema(Usuari.ESTAT_EN_SISTEMA_BLOQUEJAT);
				try {  new GestorUsuari().updateUsuari(u); } catch (Exception e) {}
				throw new ExceptionLogin("PantallaError.ErrorLogin.usuariBloquejat");
			}
			throw new ExceptionLogin("PantallaError.ErrorLogin.passwordIncorrecte");
		}
		return u;
	}
	
	private Usuari obtenirUsuari(String login) throws ExceptionServer {
		Usuari u = null;
		// FEM ARA DE MOMENT L'OBTENCIO DIRECTAMENT DE BASE DE DADES, SENSE PASSAR PER SERVIDOR RMI
		// QUAN AIXO FUNCIONI BE, JA HO CANVIARE PER A FER-HO A TRAVES DEL RMI
		u = new GestorUsuari().getUsuari(login);
		return u;
	}
	
	
	private boolean estaEnElHashMap(String login) {
		return elsIntents.containsKey(login);
	}
	
	private Integer obtenirComptadorIntents(String login) {
		if (!estaEnElHashMap(login)) return new Integer(0);
		return elsIntents.get(login);
	}
	
	private void incrementaComptadorIntents(String login) {
		if (!estaEnElHashMap(login)) afegirParell(login, new Integer(1));
		else {
			Integer i = obtenirComptadorIntents(login);
			esborrarParell(login);
			afegirParell(login, new Integer(i+1));
		}
	}
	
	private void afegirParell(String l, Integer v) { elsIntents.put(l, v); }
	
	private void esborrarParell(String login){
		if (!estaEnElHashMap(login)) return;
		elsIntents.remove(login);
	}

	public Usuari initUsuari(PantallaGestioUsuaris p) {
		Usuari u = null;
		char t = p.getTipusUsuari();
		switch (t) {
		case 'A': u = new Administrador(); break;
		case 'E': u = new Estudiante(); break;
		default: u = new ResponsableEvents(); break;
		}
		u.setIdIntern(p.getIdIntern()); // fins i tot si es null, no passa res
		u.setIdUsuari(p.getIdUsuari()); u.setPwd(p.getPwd()); u.setMail(p.getMail());
		u.setNom(p.getNom()); u.setCognom1(p.getCognom1()); u.setCognom2(p.getCognom2());
		u.setTipusUsuari(p.getTipusUsuari()); u.setTipusDocumentId(p.getTipusDocument());
		u.setDocument(p.getDocument()); u.setEstatEnSistema(p.getEstatEnSistema());
// Em falten les dates
//		setDataCreacio(u.getDataCreacio()); setDataModificacio(u.getDataModificacio()); setDataEsborrat(u.getDataEsborrat());
//		u.setDataCreacio(p. ...) ...
		if (u instanceof Estudiante) ((Estudiante)u).setUniversitat(p.getUniversitat());
		return u;
	}

	public int altaUsuari(Usuari u) throws ExceptionConnexioManteniment {
		int id = -1;
		if (u instanceof Administrador) try { id = new GestorAdministrador().insertAdministrador((Administrador)u); } catch (ExceptionServer e) { throw new ExceptionAltaUsuari(e.getErrorCode()); }
		if (u instanceof Estudiante) try { id = new GestorEstudiant().insertEstudiant((Estudiante)u); } catch (ExceptionServer e) { throw new ExceptionAltaUsuari(e.getErrorCode()); }
		if (u instanceof ResponsableEvents) try { id = new GestorResponsableEvents().insertResponsableEvents((ResponsableEvents)u); } catch (ExceptionServer e) { throw new ExceptionAltaUsuari(e.getErrorCode()); }
		return id;
	}
	public void baixaUsuari(Usuari u) throws ExceptionConnexioManteniment {
		if (u instanceof Administrador) try { new GestorAdministrador().deleteAdministrador((Administrador)u); } catch (ExceptionServer e) { throw new ExceptionBaixaUsuari(e.getErrorCode()); } 
		if (u instanceof Estudiante) try { new GestorEstudiant().deleteEstudiant((Estudiante)u); } catch (ExceptionServer e) { throw new ExceptionBaixaUsuari(e.getErrorCode()); }
		if (u instanceof ResponsableEvents) try { new GestorResponsableEvents().deleteResponsableEvents((ResponsableEvents)u); }  catch (ExceptionServer e) { throw new ExceptionBaixaUsuari(e.getErrorCode()); }
	}
	public void modificacioUsuari(Usuari u) throws ExceptionConnexioManteniment {
		if (u instanceof Administrador) try { new GestorAdministrador().updateAdministrador((Administrador)u); } catch (ExceptionServer e) { throw new ExceptionMantenimentUsuari(e.getErrorCode()); } 
		if (u instanceof Estudiante) try { new GestorEstudiant().updateEstudiant((Estudiante)u); } catch (ExceptionServer e) { throw new ExceptionMantenimentUsuari(e.getErrorCode()); }
		if (u instanceof ResponsableEvents) try { new GestorResponsableEvents().updateResponsableEvents((ResponsableEvents)u); }  catch (ExceptionServer e) { throw new ExceptionMantenimentUsuari(e.getErrorCode()); } 
	}
	
	public Vector<Usuari> getLlistaUsuaris(Estudiante criteriCerca) throws ExceptionConnexioManteniment {
		Vector<Usuari> v = new Vector<Usuari>();
		try {
			v = new GestorUsuari().getLlistaUsuaris(criteriCerca);
		} catch (ExceptionServer e) { throw new ExceptionConsultaUsuari(e.getErrorCode()); }
		return v;
	}
	
	public Usuari getUsuari(String login) throws ExceptionConnexioManteniment {
		GestorUsuari gu = new GestorUsuari();
		try { return gu.getUsuari(login); } catch (ExceptionServer e) { throw new ExceptionConsultaUsuari(e.getErrorCode()); }
	}
}